package com.qiu.util.Interceptor;

import com.alibaba.druid.pool.DruidPooledPreparedStatement;
import org.apache.ibatis.executor.statement.StatementHandler;
import org.apache.ibatis.mapping.BoundSql;
import org.apache.ibatis.mapping.MappedStatement;
import org.apache.ibatis.plugin.*;
import org.apache.ibatis.reflection.MetaObject;
import org.apache.ibatis.reflection.SystemMetaObject;
import org.assertj.core.util.Strings;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Component;

import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.Statement;
import java.util.Properties;

import com.qiu.util.threadLocalVar.ExecuteSqlStatement;

@Intercepts({
        @Signature(
                type = StatementHandler.class,
                method = "parameterize",
                args = {Statement.class}
        ), @Signature(
        type = StatementHandler.class,
        method = "prepare",
        args = {Connection.class, Integer.class}
)
})
@Component
public class SqlStatementInterceptor implements Interceptor {
    private static final Logger log = LoggerFactory.getLogger(SqlStatementInterceptor.class);

    @Override
    public Object intercept(Invocation invocation) throws Throwable {
        String methodName = invocation.getMethod().getName();
        if (methodName.equals("parameterize")) {
            Object result = invocation.proceed();
            DruidPooledPreparedStatement arg = (DruidPooledPreparedStatement) invocation.getArgs()[0];
            PreparedStatement rawStatement = arg.getRawStatement();
            String sqlLog = ExecuteSqlStatement.getSqlLabel().get() + ": " + rawStatement.toString().replaceAll("com.mysql.cj.jdbc.ClientPreparedStatement:", "");
            ExecuteSqlStatement.getSqlLabel().remove();
            //取出之前的sql日志缓存
            String temp = ExecuteSqlStatement.getLocalVar().get();
            ExecuteSqlStatement.getLocalVar().remove();

            if (Strings.isNullOrEmpty(temp)) {
                ExecuteSqlStatement.getLocalVar().set(sqlLog + "\n====================================");
            } else {
                ExecuteSqlStatement.getLocalVar().set(temp + "\n" + sqlLog + "\n====================================");
            }
            return result;
        } else if (methodName.equals("prepare")) {
            StatementHandler handler = (StatementHandler) invocation.getTarget();
            MetaObject metaObject = SystemMetaObject.forObject(handler);

            // 获取 MappedStatement 对象
            MappedStatement mappedStatement = (MappedStatement) metaObject.getValue("delegate.mappedStatement");

            // 解析 SQL ID 和 XML 文件名
            String sqlId = mappedStatement.getId();
            ExecuteSqlStatement.getSqlLabel().set(sqlId);
            return invocation.proceed();
        } else {
            log.error("拦截器出错!拦截到未知方法【{}】", methodName);
        }
        return null;
    }

    @Override
    public Object plugin(Object target) {
        // 包装所有 StatementHandler
        return Plugin.wrap(target, this);
    }

    @Override
    public void setProperties(Properties properties) {
        // 可读取配置文件中的属性（此处未使用）
    }
}